#ifndef NASCCL_CipherKey_H
#define NASCCL_CipherKey_H
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
    The CipherKey function will take any valid key and cipher it.
    This function will generate the same ciphered key every time it
    is called as long as the input key (InputKey) and the key size
    stay the same.

    This functions can also be used to remove Null, CR & LF from your keys.
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "NASCCL.H"
#include "sBoxes.H"
#include "Math.H"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool CipherKey(void *InputKey, void *OutputKey, int SizeOfKey)
{
    int LocalLoop = 0;
    int InKeyPos  = 0;
    int Box       = 0;

    NASCCLByte InKeyValue = 0;
    NASCCLByte sKeyValue  = 0;
    NASCCLByte sValue     = 0;
    NASCCLByte LastValue  = 0;
    NASCCLByte MValue1    = 0;
    NASCCLByte MValue2    = 0;

    if(SizeOfKey  >  MaxKeyLength) return false;
    if(SizeOfKey  <  MinKeyLength) return false;
    if(OutputKey == 0)             return false;
    if(InputKey  == 0)             return false;

    LastValue = ((NASCCLByte *)InputKey)[InKeyPos];

    while(LocalLoop < SizeOfKey)
    {
        InKeyValue = ((NASCCLByte *)InputKey)[InKeyPos];
        sKeyValue  = sHashBox[Box][InKeyValue];
        sValue     = sHashBox[Box][LastValue];

        MValue1 = Merge( Box, InKeyPos, LastValue, sValue, sKeyValue, InKeyValue );
        MValue2 = Merge( InKeyValue, sKeyValue, sValue, LastValue, InKeyPos, Box );

        ((NASCCLByte *)OutputKey)[LocalLoop] =
            InKeyValue               + (
            (InKeyValue ^ MValue1)   +
            (InKeyValue ^ sKeyValue) +
            (InKeyValue ^ sValue)    +
            (InKeyValue ^ LocalLoop) +
            (InKeyValue ^ LocalLoop) +
            (InKeyValue ^ MValue2)   );

        if(((NASCCLByte *)OutputKey)[LocalLoop] == LastValue)
            ((NASCCLByte *)OutputKey)[LocalLoop] += Box;

        LastValue = ((NASCCLByte *)OutputKey)[LocalLoop];

        if(((NASCCLByte *)OutputKey)[LocalLoop] == 0 ) // Null
            ((NASCCLByte *)OutputKey)[LocalLoop] += 16;
        else if(((NASCCLByte *)OutputKey)[LocalLoop] == 10) // LF
            ((NASCCLByte *)OutputKey)[LocalLoop] += 24;
        else if(((NASCCLByte *)OutputKey)[LocalLoop] == 13) // CR
            ((NASCCLByte *)OutputKey)[LocalLoop] += 32;

        if(Box == BoxSize)
            Box = -1;

        LocalLoop++;
        InKeyPos++;
        Box++;
    }

    return true;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif

